const version = require("element-ui/package.json").version; // element-ui version from node_modules
const ORIGINAL_THEME = "#409EFF"; // default color
const ALPHA = "0.6";

export default {
  data() {
    return {
      size: "small",
      default: null,
      chalk: "", // content of theme-chalk css
      theme: ORIGINAL_THEME,
      showSuccess: true, // 是否弹出换肤成功消息
    };
  },
  mounted() {
    if (this.default != null) {
      this.theme = this.default;
      this.$emit("onThemeChange", this.theme);
      this.showSuccess = false;
    }
  },
  watch: {
    "$store.state.themeColor": {
      handler(val) {
        this.theme = val;
      },
      immediate: true,
    },
    theme: {
      handler(val, oldVal = "#409EFF") {
        this.setElementTheme(val);
        this.changeFontSize();
        if (typeof val !== "string") return;
        const themeCluster = this.getThemeCluster(val.replace("#", ""));
        const originalCluster = this.getThemeCluster(oldVal.replace("#", ""));
        const getHandler = (variable, id) => {
          return () => {
            const originalCluster = this.getThemeCluster(
              ORIGINAL_THEME.replace("#", "")
            );
            const newStyle = this.updateStyle(
              this[variable],
              originalCluster,
              themeCluster
            );

            let styleTag = document.getElementById(id);
            if (!styleTag) {
              styleTag = document.createElement("style");
              styleTag.setAttribute("id", id);
              document.head.appendChild(styleTag);
            }
            styleTag.innerText = newStyle;
          };
        };

        const chalkHandler = getHandler("chalk", "chalk-style");

        if (!this.chalk) {
          const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`;
          this.getCSSString(url, chalkHandler, "chalk");
        } else {
          chalkHandler();
        }
        const styles = [].slice
          .call(document.querySelectorAll("style"))
          .filter((style) => {
            const text = style.innerText;
            return (
              new RegExp(oldVal, "i").test(text) &&
              !/Chalk Variables/.test(text)
            );
          });
        styles.forEach((style) => {
          const { innerText } = style;
          if (typeof innerText !== "string") return;
          style.innerText = this.updateStyle(
            innerText,
            originalCluster,
            themeCluster
          );
        });

        // 响应外部操作
        this.$emit("onThemeChange", val);
        if (this.showSuccess) {
          // this.$message({
          //   message: "换肤成功",
          //   type: "success",
          // });
        } else {
          this.showSuccess = true;
        }
      },
      immediate: true,
    },
  },
  methods: {
    // 十六进制转 rgb
    hexToRgb(hex) {
      return (
        "rgba(" +
        parseInt("0x" + hex.slice(1, 3)) +
        "," +
        parseInt("0x" + hex.slice(3, 5)) +
        "," +
        parseInt("0x" + hex.slice(5, 7)) +
        ")"
      );
    },

    // 设置字体大小
    changeFontSize(val) {
      let root = document.documentElement;
      root.style.setProperty("--font-size", this.fontSize);
    },

    // 设置普通样式主题
    setElementTheme(val) {
      this.$nextTick(() => {
        let reg = /(?<=\().*?(?=\))/;
        let rgb = this.hexToRgb(val).match(reg)[0];
        let rgba = `rgba(${rgb},1)`;
        let root = document.documentElement;
        root.style.setProperty("--theme-primary-color", rgba);
        root.style.setProperty("--theme-light-color", `rgba(${rgb},${ALPHA})`);
      });
    },

    updateStyle(style, oldCluster, newCluster) {
      let newStyle = style;
      oldCluster.forEach((color, index) => {
        newStyle = newStyle.replace(new RegExp(color, "ig"), newCluster[index]);
      });
      return newStyle;
    },

    getCSSString(url, callback, variable) {
      const xhr = new XMLHttpRequest();
      xhr.onreadystatechange = () => {
        if (xhr.readyState === 4 && xhr.status === 200) {
          this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, "");
          callback();
        }
      };
      xhr.open("GET", url);
      xhr.send();
    },

    getThemeCluster(theme) {
      const tintColor = (color, tint) => {
        let red = parseInt(color.slice(0, 2), 16);
        let green = parseInt(color.slice(2, 4), 16);
        let blue = parseInt(color.slice(4, 6), 16);

        if (tint === 0) {
          // when primary color is in its rgb space
          return [red, green, blue].join(",");
        } else {
          red += Math.round(tint * (255 - red));
          green += Math.round(tint * (255 - green));
          blue += Math.round(tint * (255 - blue));

          red = red.toString(16);
          green = green.toString(16);
          blue = blue.toString(16);

          return `#${red}${green}${blue}`;
        }
      };

      const shadeColor = (color, shade) => {
        let red = parseInt(color.slice(0, 2), 16);
        let green = parseInt(color.slice(2, 4), 16);
        let blue = parseInt(color.slice(4, 6), 16);

        red = Math.round((1 - shade) * red);
        green = Math.round((1 - shade) * green);
        blue = Math.round((1 - shade) * blue);

        red = red.toString(16);
        green = green.toString(16);
        blue = blue.toString(16);

        return `#${red}${green}${blue}`;
      };

      const clusters = [theme];
      for (let i = 0; i <= 9; i++) {
        clusters.push(tintColor(theme, Number((i / 10).toFixed(2))));
      }
      clusters.push(shadeColor(theme, 0.1));
      return clusters;
    },
  },
};
